/*
 *  Copyright (C) 2010 Matthias Buch-Kromann <mbk.isv@cbs.dk>
 * 
 *  This file is part of the MatrixParser package.
 *  
 *  The MatrixParser program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.osdtsystem.matrixparser.parsers;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.osdtsystem.matrixparser.data.CONLLSentence;
import org.osdtsystem.matrixparser.data.CONLLToken;
import org.osdtsystem.matrixparser.parsers.output.DependencyTree;
import org.osdtsystem.matrixparser.featureextraction.FirstOrderExtractorLabelled;
import org.osdtsystem.matrixparser.featureextraction.FirstOrderExtractorUnlabelled;
import org.osdtsystem.matrixparser.features.DefaultMstCache;
import org.osdtsystem.matrixparser.features.FeatureVector;
import org.osdtsystem.matrixparser.features.FeatureVectorFactory;
import org.osdtsystem.matrixparser.features.MstCache;
import org.osdtsystem.matrixparser.features.TwoWayFeatureHandler;
import org.osdtsystem.matrixparser.learners.Scorer;
import org.osdtsystem.matrixparser.logging.Log;

/**
 *
 * @author Matthias Buch-Kromann <mbk.isv@cbs.dk>
 */
public abstract class AbstractParser implements Parser {
    int lastComplementId = Integer.MAX_VALUE;
    final Scorer scorer;
    final String name;
    private final FirstOrderExtractorUnlabelled unlabelledMstExtractor;
    private final FirstOrderExtractorLabelled labelledMstExtractor;
    final TwoWayFeatureHandler labelAlphabet;
    final int rootLabel;
    
    // Cache
    private MstCache mstCache;
    private CONLLSentence cachedSentence;
    
    public AbstractParser(String name, Scorer scorer,
            FirstOrderExtractorUnlabelled unlabelledMstExtractor,
            FirstOrderExtractorLabelled labelledMstExtractor,
            TwoWayFeatureHandler labelAlphabet) {
        this.name = name;
        this.unlabelledMstExtractor = unlabelledMstExtractor;
        this.labelledMstExtractor = labelledMstExtractor;
        this.labelAlphabet = labelAlphabet;
        this.scorer = scorer;
        this.rootLabel = labelAlphabet.getFeature("<ROOT>").id();
    }

    public Scorer scorer() {
        return (scorer);
    }

    final MstCache mstCache(CONLLSentence sentence) {
        if (sentence != cachedSentence) {
            cachedSentence = sentence;
            mstCache = new DefaultMstCache(sentence,
                    unlabelledMstExtractor, labelledMstExtractor, labelAlphabet);
        }
        return mstCache;
    }

    public static int readComplements(String complementFile, TwoWayFeatureHandler labelHandler) {
        BufferedReader input = null;
        int complementID = 0;
        if (complementFile.equals(""))
            return 0;
        try {
            input = new BufferedReader(new InputStreamReader(new FileInputStream(complementFile), "UTF8"));
            String line;
            while ((line = input.readLine()) != null) {
                Log.config("Complement: '" + line + "'");
                complementID = labelHandler.getFeature(line).id();
            }
        } catch (IOException ex) {
            Logger.getLogger(IncrementalLabMSTParser.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                input.close();
            } catch (IOException ex) {
                Logger.getLogger(IncrementalLabMSTParser.class.getName()).log(Level.SEVERE, null, ex);
            }
            return complementID;
        }
    }

    public void setLastComplementID(int id) {
        lastComplementId = id;
    }

    public DependencyTree goldTree(CONLLSentence sentence) {
        DependencyTree tree = new DependencyTree(sentence, labelAlphabet, lastComplementId);
        for (int node = 1; node < sentence.size(); ++node) {
            CONLLToken nodeToken = sentence.get(node);
            int head = nodeToken.head();
            String labelName = nodeToken.deprel();
            int label = labelAlphabet.getFeature(labelName).id();
            tree.setDependency(node, head, label);
        }
        tree.setLastnode(100000);
        tree.setLeftscan(0);
        return tree;
    }

    public final FeatureVector featureVector(DependencyTree tree) {
        return FeatureVectorFactory.union(featureVectors(tree));
    }

    final List<FeatureVector> featureVectors(DependencyTree tree) {
        return featureVectors(tree, new ArrayList<FeatureVector>());
    }

    abstract List<FeatureVector> featureVectors(DependencyTree tree,
            List<FeatureVector> aggregator);

    public String name() {
        return name;
    }
}
